package model;

import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;

public class CompositeCollisionMap  implements CollisionMap {

	private int[][] collisionGrid;
	
	public CompositeCollisionMap(){
		collisionGrid = new int[0][0];
	}
	public CompositeCollisionMap(BufferedImage img){
		//compute bitgrid from a bitmap
		WritableRaster transpRaster = img.getAlphaRaster();
		int width = transpRaster.getWidth();
		int height = transpRaster.getHeight();
		collisionGrid = new int[width][height];
		for(int y=0;y<height;y++){
			for(int x=0;x<width;x++){
				collisionGrid[x][y] = (transpRaster.getSample(x, y, 0) > 0)?1:0;
			}
		}
	}
	private CompositeCollisionMap(int[][] collGrid){
		collisionGrid = collGrid;
	}
	
	public String toString(){
		int width = collisionGrid.length;
		if(width>0){
			String returnstr="";
			int height = collisionGrid[0].length;
			for(int y=0;y<height;y++){
				for(int x=0;x<width;x++){
					returnstr+=collisionGrid[x][y];
				}
				returnstr+="\n";
			}
			return returnstr;
		}else return"";
	}
	
	public int getWidth(){
		return collisionGrid.length;
	}
	
	public int getHeight(){
		if(collisionGrid.length>0)
			return collisionGrid[0].length;
		else
			return 0; 
	}
	public int get(int x,int y){
		return collisionGrid[x][y];
	}
	
	public CompositeCollisionMap getExtract(int origx,int origy,int tox,int toy){
		
		int[][] collGrid = new int[tox-origx][toy-origy];
		for(int x=0;x<tox-origx;x++){
			for(int y=0;y<toy-origy;y++){
				collGrid[x][y] = collisionGrid[origx+x][origy+y];
			}
		}
		
		return new CompositeCollisionMap(collGrid);
	}
	
	public int[] add(int[] position, CollisionMap toAdd){
		int[] decal = null;//potential decal of the resulting grid to return
	 
		 //if the added map is out of this map, we reconstruct a map to take these two
		 if(position[0]<0 || position[1]<0 || position[0]+toAdd.getWidth()>getWidth() || position[1]+toAdd.getHeight()>getHeight()){
			 int[][] newCollisionGrid; 			   //the new grid
			 decal = new int[2];				   //decal of the resulting grid
			 if(position[0]<0)decal[0]=position[0];
			 if(position[1]<0)decal[1]=position[1];
			 int width=(position[0]+toAdd.getWidth()>getWidth())?position[0]+toAdd.getWidth():getWidth();
			 int height=(position[1]+toAdd.getHeight()>getHeight())?position[1]+toAdd.getHeight():getHeight();
	 
			 newCollisionGrid = new int[width][height];
			 //we add the old grid to the new one
			 for(int y=0;y<height;y++){
					for(int x=0;x<width;x++){
						//if the point is inside the existant grid
						if(x-decal[0]<getWidth() && y-decal[1]<getHeight()){
							if(collisionGrid[x][y]>0)newCollisionGrid[x-decal[0]][y-decal[1]]+=collisionGrid[x][y];
						}
					}
			 }
		 
			 collisionGrid=newCollisionGrid;
			 //and we ajust the position of the added map
			 position[0]-=decal[0];
			 position[1]-=decal[1];
			 
			 assert position[0]>=0;
			 assert position[1]>=0;
		 }
		 
		 
		 for(int y=0;y<toAdd.getHeight();y++){
//System.out.println(y);			 
			for(int x=0;x<toAdd.getWidth();x++){
//System.out.println(x);			 
				//si on a une valeur dans la grille de base, alors on l'ajoute
				if(toAdd.get(x, y)>0)collisionGrid[x+position[0]][y+position[1]]+=toAdd.get(x, y);
			}
		}
		
		return decal;
	}
	
	public void remove(int[] position, CollisionMap toRemove){
		
		//toRemove grid is inside this grid !
		
		for(int y=0;y<toRemove.getHeight();y++){
			for(int x=0;x<toRemove.getWidth();x++){
				//si on a une valeur dans la grille de base, alors on l'ajoute
				if(toRemove.get(x,y)>0){
					if(0<x+position[0] && x+position[0]<getWidth()  &&  0<y+position[1]&&y+position[1]<getHeight()){
						collisionGrid[x+position[0]][y+position[1]]-=toRemove.get(x,y);
						if(collisionGrid[x+position[0]][y+position[1]]<0)collisionGrid[x+position[0]][y+position[1]]=0;
					}
				}
			}
		}
	}
	
	/*
	 * 
	 * 
	 * never used anymore --> the collision map can't position from the origin of the Sprite
	 * 
	 * 
	 * 
	private int[] crop(){
		//watch if the borders are utils: if they are populated with '0', we delete them.
		int[] decal = null;
		int minY=0,maxY=getHeight(),minX=0,maxX=getWidth();
				
		
		boolean found=false;
		for(;maxY>minY&&!found;minY=(found)?minY:minY+1){
			for (int x=minX;x<maxX&&!found;x++){
				found=collisionGrid[x][minY]>0;
			}
		}	
		
		found=false;
		for(;maxY>minY&&!found;maxY=(found)?maxY:maxY-1){
			for (int x=minX;x<maxX&&!found;x++){
				found=collisionGrid[x][maxY-1]>0;
			}
		}

		
		found=false;
		for(;maxX>minX&&!found;minX=(found)?minX:minX+1){
			for (int y=minY;y<maxY&&!found;y++){
				found=collisionGrid[minX][y]>0;
			}
		}

		
		found=false;
		for(;maxX>minX&&!found;maxX=(found)?maxX:maxX-1){
			for (int y=minY;y<maxY&&!found;y++){
				found=collisionGrid[maxX-1][y]>0;
			}
		}
	
		
		//if a usefull bit has been found
		if(found){
			//if the grid has changed
			if(minY>0 || maxY<getHeight() || minX>0 || maxX < getWidth()){
				decal = new int[2];
				decal[0]=minX;
				decal[1]=minY;
				int[][] newGrid = new int[maxX-minX][maxY-minY];
				for(int x=0;x<newGrid.length;x++){
					for(int y=0;y<newGrid[0].length;y++){
						newGrid[x][y]=collisionGrid[x+decal[0]][y+decal[1]];
					}
				}
				collisionGrid=newGrid;
			}
		}else{
			collisionGrid = new int[0][0];
		}
		
		return decal;
	}
	*/
}
